package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.Constants;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.dubbo.api.QuestionApi;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.RecommendUserApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.dubbo.api.mongo.UserLocationApi;
import com.tanhua.dubbo.api.mongo.VisitorApi;
import com.tanhua.model.db.Question;
import com.tanhua.model.db.User;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.UserLike;
import com.tanhua.model.mongo.UserLocation;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.*;
import com.tanhua.server.interceptor.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 首页交友管理业务处理层
 */
@Service
@Slf4j
public class TanhuaService {
    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @DubboReference
    private UserApi userApi;

    @DubboReference
    private UserLikeApi userLikeApi;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private UserLocationApi userLocationApi;


    @DubboReference
    private VisitorApi visitorApi;


    /**
     *  今日佳人
     */
    public TodayBestVo todayBest() {
        Long loginUserId = UserHolder.getUserId();//当前用户id
        //1根据当前用户id查询今日佳人（recommendUser表 缘分值最高的一条记录）
        RecommendUser recommendUser = recommendUserApi.findMaxScore(loginUserId);
        //2第一步有可能没有查询到推荐数据，设置客服（默认用户数据）
        if(recommendUser == null){ //这里理论情况被执行概率不大
            recommendUser = new RecommendUser();
            long serviceUserId = loginUserId%99+1;
            recommendUser.setUserId(serviceUserId);//推荐的客户用户id
            recommendUser.setToUserId(loginUserId);//当前用户id
            recommendUser.setScore(99d);//缘分值
        }
        //3根据推荐用户id查询tb_userInfo表
        UserInfo userInfo = userInfoApi.findUserInfo(recommendUser.getUserId());
        //4基于userInfo recommendUser构造TodayBestVo返回
        return TodayBestVo.init(userInfo,recommendUser);
    }

    /**
     *  首页推荐用户分页列表
     */
    public PageResult<TodayBestVo> findPageRecommendUser(RecommendUserVo ruv) {
        log.debug("******************RecommendUserVo{}********************",ruv.toString());
        Long loginUserId = UserHolder.getUserId();//当前登录用户id
        Long page = ruv.getPage();//当前页码
        Long pagesize = ruv.getPagesize();//每页显示条数
        Integer age = ruv.getAge();//年龄
        String gender = ruv.getGender();//性别
        //1 根据当前登录用户id分页查询推荐用户列表数据
        PageResult<RecommendUser> pageResult = recommendUserApi.findPageRecommendUser(loginUserId,page,pagesize);
        log.debug("******************pageResult{}********************",pageResult.toString());
        //2 第一步有可能没有查询到推荐数据，默认设置客服数据
        if(pageResult == null || CollectionUtils.isEmpty(pageResult.getItems())){
            //默认推荐用户列表数据
            List<RecommendUser> defaultRecommendUserList = getDefaultRecommendUserList();
            //设置到PageResult对象中
            pageResult.setCounts(10l);//总记录数
            pageResult.setPagesize(pagesize);//当前页面显示条数
            pageResult.setPage(page);//当前页码
            pageResult.setItems(defaultRecommendUserList);//默认当前页面数据
        }
        List<RecommendUser> recommendUserList = pageResult.getItems();
        //3 获取所有推荐用户ids List<long>
        List<Long> serviceUserIds = recommendUserList.stream().map(RecommendUser::getUserId).collect(Collectors.toList());
        log.debug("******************serviceUserIds{}********************",serviceUserIds.toString());
        //4 根据所有推荐用户ids 查询推荐用户数据查询tb_userinfo
        UserInfo condition = new UserInfo();
        condition.setAge(age);//条件：年龄
        condition.setGender(gender);//条件：性别
        //List<UserInfo> list = userInfoApi.findByCondition(serviceUserIds,condition);
        //key:推荐用户id  value：userInfo
        Map<Long,UserInfo> userInfoMap = userInfoApi.findByCondition(serviceUserIds,condition);
        log.debug("******************userInfoMap{}********************",userInfoMap.toString());
        //5 基于UserInfo RecommendUser数据构造TodayBestVo返回
        //5.1定义List集合接收vo返回
        List<TodayBestVo> todayBestVoList = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUserList) {
            Long serviceUserId = recommendUser.getUserId();//推荐用户id
            UserInfo userInfo = userInfoMap.get(serviceUserId);//根据推荐用户id获取推荐用户对象
            if(userInfo != null) {
                TodayBestVo todayBestVo = TodayBestVo.init(userInfo, recommendUser);
                todayBestVoList.add(todayBestVo);
            }
        }
        return new PageResult<>(page,pagesize,pageResult.getCounts(),todayBestVoList);
    }


    /**
     * 默认客服
     * @return
     */
    private List<RecommendUser> getDefaultRecommendUserList(){
        List<RecommendUser> list = new ArrayList<>();
        // 随机产生开始的客户id, 从这个客服的id开始，往后取10个
        int startIndex = RandomUtils.nextInt(1,90);
        RecommendUser recommendUser = null;
        for (long i = startIndex; i<startIndex+10; i++) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(i);
            recommendUser.setScore(RandomUtils.nextDouble(70,88));
            list.add(recommendUser);
        }
        return list;
    }

    /**
     * 获取佳人用户详情
     * @param personUserId
     * @return
     */
    public TodayBestVo personalInfo(Long personUserId) {
        //1.根据personUserId查询recommendUser表
        RecommendUser recommendUser = recommendUserApi.findByUserId(personUserId,UserHolder.getUserId());
        //2根据推荐用户id查询tb_userInfo表
        UserInfo userInfo = userInfoApi.findUserInfo(personUserId);
        //2.1 保存当前登录用户访客佳人记录
        Visitors visitors = new Visitors();
        visitors.setUserId(personUserId);//被访客的用户id
        visitors.setVisitorUserId(UserHolder.getUserId());//访客的用户id-当前登录用户
        visitors.setFrom("首页");//来源，如首页. 圈子等
        visitors.setScore(recommendUser.getScore());//缘分值
        visitorApi.add(visitors);
        log.debug("*********visitorApi****add**保存访客数据成功了******");
        //3基于userInfo recommendUser构造TodayBestVo返回
        return TodayBestVo.init(userInfo,recommendUser);
    }

    /**
     *  查看陌生人问题
     */
    public String strangerQuestions(Long userId) {
        Question question = questionApi.findQuestionById(userId);
        String txt = "约吗?";//默认值
        if (question != null) {
            txt = question.getTxt();
        }
        log.debug("*************查看陌生人问题{}**************",question);
        return txt;
    }

    /**
     *  回复陌生人问题
     *  需要发送的消息内容：
     *  {"userId":106,"huanXinId":"hx106","nickname":"黑马小妹","strangerQuestion":"你喜欢去看蔚蓝的大海还是去爬巍峨的高山？",
     *  "reply":"我喜欢秋天的落叶，夏天的泉水，冬天的雪地，只要有你一切皆可~"}
     */
    public void replyStrangerQuestions(Long personUserId, String reply) {
        log.debug("*********personUserId**{}*********reply****{}*******",personUserId,reply);
        User user = UserHolder.getUser(); //当前登录用户对象
        //1.根据当前用户id查询tb_user表 获取环信用户id 用户昵称
        Long loginUserId = user.getId();//当前登录用户id
        String hxUser = user.getHxUser();//当前登录用户环信账号
        //1.1 根据当前登录用户id查询登录用户详情
        UserInfo loginUserInfo = userInfoApi.findUserInfo(loginUserId);
        String loginNickname = loginUserInfo.getNickname();//当前登录用户昵称
        //2.查询佳人问题
        Question question = questionApi.findQuestionById(personUserId);
        String txt = "约吗?";//默认值
        if (question != null) {
            txt = question.getTxt();
        }
        log.debug("*************查看陌生人问题{}**************",question);

        //3.根据佳人用户id查询佳人环信账号
        User personUser = userApi.findById(personUserId);

        //4.构造数据调用环信发送消息
        Map map = new HashMap();
        map.put("userId",loginUserId);
        map.put("huanXinId",hxUser);
        map.put("nickname",loginNickname);
        map.put("strangerQuestion",txt);
        map.put("reply",reply);
        String content = JSON.toJSONString(map);//需要发送的消息
        log.debug("********************content*****{}****************",content);
        String username = personUser.getHxUser();//给哪个用户发送消息 接收好友请求环信用户id hx1
        log.debug("********************username*****{}****************",username);
        try {
            huanXinTemplate.sendMsg(username,content);
        } catch (Exception e) {
            log.debug("************环信发送消息失败了*******************");
            throw new TanHuaException(ErrorResult.error());
        }
        log.debug("*******当前用户{}*************发送申请加好友消息成功了*****{}****************",hxUser,username);

    }

    //指定默认数据（如果希望客服数据不再重复推荐 设计客服表 随机从中查询-排除推荐过）
    @Value("${tanhua.default.recommend.users}")
    private String recommendUserIds;

    /**
     *  探花-左滑右滑 随机查询10个推荐用户
     */
    public List<TodayBestVo> findCards() {
        Long loginUserId = UserHolder.getUserId();//当前登录用户id
        //1 调用服务根据当前登录用户id查询RecommendUser表随机查10条数据
        List<RecommendUser> recommendUserList = recommendUserApi.findCards(loginUserId);
        //2 如果没有查询到设置默认推荐用户数据（10条）
        if(CollectionUtils.isEmpty(recommendUserList)){
            recommendUserList = new ArrayList<>();
            //recommendUserIds:假数据（客服ids）
            String[] userIds = StringUtils.split(recommendUserIds, ",");
            for (String userId : userIds) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Long.valueOf(userId));
                recommendUser.setScore(RandomUtils.nextDouble(70,80));
                recommendUserList.add(recommendUser);
            }
        }
        //3 获取推荐用户ids
        List<Long> recommendUserIds = recommendUserList.stream().map(RecommendUser::getUserId).collect(Collectors.toList());
        log.debug("************************recommendUserIds********************"+recommendUserIds);
        //4 根据推荐用户ids查询用户详情（tb_userinfo）
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByCondition(recommendUserIds, null);
        //5 基于tb_userInfo recommendUser构造vo
        List<TodayBestVo> bestVoList = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUserList) {
            UserInfo userInfo = userInfoMap.get(recommendUser.getUserId());//根据推荐用户的id查询推荐用户详情
            bestVoList.add(TodayBestVo.init(userInfo,recommendUser));
        }
        log.debug("************************bestVoList********************"+bestVoList);
        return bestVoList;
    }

    /**
     * 探花-左滑右滑业务处理实现
     * @param recommendUserId 推荐用户id
     * @param isLove 是否喜欢 true：喜欢 false:不喜欢
     */
    public void love(Long recommendUserId, boolean isLove) {
        log.debug("***********recommendUserId**{}**************isLove*{}*********",recommendUserId,isLove);
        Long loginUserId = UserHolder.getUserId();//当前登录用户id
        //1 调用服务保存喜欢或不喜欢数据
        UserLike userLike = new UserLike();
        userLike.setUserId(loginUserId);//当前用户id
        userLike.setLikeUserId(recommendUserId);//喜欢或不喜欢的用户id
        userLike.setIsLike(isLove);//是否喜欢true false
        boolean isFriend = userLikeApi.add(userLike);
        log.debug("***********isFriend**{}***************",isFriend);
        //喜欢key
        String likeKey = Constants.USER_LIKE_KEY + UserHolder.getUserId();
        //不喜欢key
        String unlikeKey = Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId();
        if(isLove) {
            //2 将用户id添加喜欢集合，从不喜欢集合移除 (目前还未使用到数据-后续进行统计分析)
            stringRedisTemplate.opsForSet().add(likeKey,recommendUserId.toString());
            stringRedisTemplate.opsForSet().remove(unlikeKey,recommendUserId.toString());
        }else {
            //3 将用户id添加不喜欢集合，从喜欢集合移除
            stringRedisTemplate.opsForSet().remove(likeKey,recommendUserId.toString());
            stringRedisTemplate.opsForSet().add(unlikeKey,recommendUserId.toString());
        }
        //4 如果是互相喜欢调用环信云保存好友关系（喜欢+对方也喜欢我）
        if(isLove && isFriend){
            try {
                huanXinTemplate.addContact(Constants.HX_USER_PREFIX+loginUserId,Constants.HX_USER_PREFIX+recommendUserId);
                log.debug("***********调用环信添加好友成功了****************");
            } catch (Exception e) {
                log.debug("**************添加好友失败了或好友关系已经存在了*******************");
            }
        }

    }

    /*
     *搜附近
     */
    public List<NearUserVo> searchNearUser(String gender, Long distance) {
        log.debug("**************gender****{}**********distance****{}***************",gender,distance);
        Long loginUserId = UserHolder.getUserId();//当前登录用户id
        //1.调用服务获取附近用户ids userLocation表中数据
        List<Long> nearUserIds =  userLocationApi.searchNearUser(loginUserId,distance);
        log.debug("**************nearUserIds***{}***************",nearUserIds);
        List<NearUserVo> nearUserVoList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(nearUserIds)){
            //2.根据附近用户ids和性别查询tb_userInfo
            UserInfo userInfo = new UserInfo();
            userInfo.setGender(gender);
            Map<Long, UserInfo> userInfoMap = userInfoApi.findByCondition(nearUserIds, userInfo);

            //3.基于userInfo数据构造VO
            for (Long nearUserId : nearUserIds) {
                UserInfo ui = userInfoMap.get(nearUserId);
                if(ui != null){
                    nearUserVoList.add(NearUserVo.init(ui));
                }
            }
        }
        log.debug("**************nearUserVoList***{}***************",nearUserVoList);
        return nearUserVoList;
    }
}
